/* (c)2010-2012 Andrea Caltroni (andrea.caltroni@pd.infn.it), INFN (www.infn.it)
 *
 * This file is part of the IGI Survey Portlet (from here on shortened to IGISP).
 * IGISP is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) any 
 * later version.
 *
 * IGISP is distributed in the hope that it will be useful, but WITHOUT ANY 
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with IGISP. If not, see <http://www.gnu.org/licenses/>.
 */
package it.infn.grid.liferay.survey.modules.admin.controller;

import it.infn.grid.liferay.survey.modules.admin.web.SurveyStatusPropertyEditor;
import it.infn.grid.liferay.survey.modules.admin.web.SurveyValidator;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.portlet.ActionResponse;
import javax.portlet.RenderRequest;

import org.ajm.spring.survey.modules.admin.model.Survey;
import org.ajm.spring.survey.modules.admin.model.SurveyStatus;
import org.ajm.spring.survey.modules.admin.service.SurveyService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.support.PagedListHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.portlet.bind.PortletRequestDataBinder;

/**
 * The controller for the list surveys, view survey details and delete survey
 * operations on the Survey object.
 * 
 * <p>NOTE<br />
 * For a bug in Spring (see https://jira.springsource.org/browse/SPR-9303 and 
 * https://jira.springsource.org/browse/SPR-9605, apparently, this is fixed in 3.1.3.)
 * we need to use the @RequestMapping annotation in the controller with the default
 * action. Another solution is to separate this controller in a scan performed
 * after the scan of all other controllers.</p>
 * 
 * @author Andrea Caltroni, andrea.caltroni@pd.infn.it, INFN
 */
@RequestMapping(value="VIEW")
@Controller(value="surveyController")
public class SurveyController {
    
    // ------------------------------------------------------------------------|
    // --- CONSTANTS ----------------------------------------------------------|
    // ------------------------------------------------------------------------|

    // Default value that will be overwritten by the value in the portlet 
    // preferences if present
    //public static final int DEFAULT_PAGE_SIZE = 10;
    
    // --- CLASS VARIABLES ----------------------------------------------------|
    // ------------------------------------------------------------------------|
    // ------------------------------------------------------------------------|

    static Logger logger = Logger.getLogger(SurveyController.class);
    
    // ------------------------------------------------------------------------|
    // --- INSTANCE VARIABLES -------------------------------------------------|
    // ------------------------------------------------------------------------|

    private int pageSize = SavePreferencesController.NUM_ITEMS_PER_PAGE;
    
    @Autowired
    @Qualifier("surveyService")
    private SurveyService surveyService;
    
    @Autowired
    @Qualifier("surveyValidator")
    private SurveyValidator surveyValidator = new SurveyValidator();
    
    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    
    // ------------------------------------------------------------------------|
    // --- CONSTRUCTORS -------------------------------------------------------|
    // ------------------------------------------------------------------------|

    // ------------------------------------------------------------------------|
    // --- CLASS METHODS ------------------------------------------------------|
    // ------------------------------------------------------------------------|

    // ------------------------------------------------------------------------|
    // --- INSTANCE METHODS ---------------------------------------------------|
    // ------------------------------------------------------------------------|

    /**
     * Setup binder for adding/editing surveys.
     */
    @InitBinder("survey")
    protected void initBinder(PortletRequestDataBinder binder) {
        
        getDateFormat().setLenient(false);
        binder.registerCustomEditor(Date.class, null, new CustomDateEditor(dateFormat, false));

        binder.registerCustomEditor(SurveyStatus.class, new SurveyStatusPropertyEditor());
        
        //binder.setAllowedFields(new String[] {"name", "description", "status", "expiration","questions"});
    }

    // ------------------------------------------------------------------------|

    /**
     * The action for showing the list of surveys. This is the default action.
     * @param pageNumber 
     * @param pagedListHolder 
     * @param request 
     * 
     * @param model 
     * @return The attribute in the model defining the action of listing all surveys.
     */
    @RequestMapping
    public String listSurveys(@RequestParam(value="p", required=false) Integer pageNumber,
            @ModelAttribute("pagedListHolder") PagedListHolder<Survey> pagedListHolder,
            RenderRequest request, Model model) {
        
        List<Survey> surveyList = getSurveyService().findAll();
        
        pagedListHolder = new PagedListHolder<Survey>(surveyList);
        
        // retrieve from the user preferences
        setPageSize(new Integer(request.getPreferences().getValue("noOfItemsPerPage", "" + SavePreferencesController.NUM_ITEMS_PER_PAGE)).intValue());
        
        // add to the model and to the paged list holder
        model.addAttribute("pageSize", new Integer(getPageSize()));
        pagedListHolder.setPageSize(getPageSize());

        // set page
        // NOTE Spring MVC insists on passing null when non-required request parameters 
        // are left empty
        if (pageNumber == null || pageNumber.intValue() < 0) {
            model.addAttribute("p", new Integer(0));
            pagedListHolder.setPage(0);
        }
        else {
            model.addAttribute("p", pageNumber);
            pagedListHolder.setPage(pageNumber.intValue());
        }

        model.addAttribute("pagedListHolder", pagedListHolder);
        
        return "surveys";
    }

    // ------------------------------------------------------------------------|

    /**
     * The action for viewing a survey.
     * 
     * @param surveyId 
     * @param model 
     * @return The attribute in the model defining the action of viewing the 
     * details of a survey.
     */
    // TODO this should probably be a @RenderMapping
    @RequestMapping(params="action=viewSurvey")
    public String viewSurvey(@RequestParam("surveyID") Long surveyId, Model model) {
        
        model.addAttribute("survey", surveyService.findById(surveyId));
        
        return "surveyView";
    }
    
    // ------------------------------------------------------------------------|

    /**
     * The action for deleting a survey.
     * 
     * TODO Currently param is ID for compatibility with example.
     * Param should become the actual object to delete to reflect the service method.
     * 
     * TODO check that all questions and answers for this survey are deleted too.
     * 
     * @param response 
     * @param surveyId 
     */
    // TODO this should probably be a @ActionMapping
    @RequestMapping(params="action=deleteSurvey")
    public void deleteSurvey(@RequestParam("surveyID") Long surveyId, ActionResponse response) {
        
        Survey survey = getSurveyService().findById(surveyId);
        getSurveyService().delete(survey);
    }
    
    // --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --|
    // ---[  GETTERS AND SETTERS  ]--------------------------------------------|
    // --- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --|

    /**
     * @param surveyService the surveyService to set
     */
    public void setSurveyService(SurveyService surveyService) {
        
        this.surveyService = surveyService;
    }

    // ------------------------------------------------------------------------|

    /**
     * @return the surveyService
     */
    public SurveyService getSurveyService() {
        
        return surveyService;
    }

    // ------------------------------------------------------------------------|

    /**
     * @param surveyValidator the surveyValidator to set
     */
    public void setSurveyValidator(SurveyValidator surveyValidator) {
        
        this.surveyValidator = surveyValidator;
    }

    // ------------------------------------------------------------------------|

    /**
     * @return the surveyValidator
     */
    public SurveyValidator getSurveyValidator() {
        
        return surveyValidator;
    }

    // ------------------------------------------------------------------------|

    /**
     * @return the dateFormat
     */
    public SimpleDateFormat getDateFormat() {
        
        return dateFormat;
    }

    // ------------------------------------------------------------------------|

    /**
     * @param dateFormat the dateFormat to set
     */
    public void setDateFormat(SimpleDateFormat dateFormat) {
        
        this.dateFormat = dateFormat;
    }

    // ------------------------------------------------------------------------|

    /**
     * @return the pageSize
     */
    public int getPageSize() {
        return pageSize;
    }

    // ------------------------------------------------------------------------|

    /**
     * @param pageSize the pageSize to set
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    // ------------------------------------------------------------------------|

}